package tcp

import (
	
	"godis/interface/tcp"

	"context"
	"fmt"
	"net"
	"os/signal"
	"os"
	"time"
	"syscall"
	"sync"
)

//Config stores tcp server properties
type Config struct {
	Address string 	`yaml:"address"`
	MaxConnect uint32 	`yaml:"max-connect"`
	Timeout 	time.Duration	`yaml:"timeout"`
}

//ListenAndServeWithSignal bins port and handle requests. blocking util receive stop signal
func ListenAndServeWithSignal(cfg *Config, handler tcp.Handler) error {
	closeChan := make(chan struct{})
	sigCh := make(chan os.Signal)

	signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGQUIT,syscall.SIGTERM,syscall.SIGINT)
	go func() {
		sig := <-sigCh
		switch sig {
		case syscall.SIGHUP, syscall.SIGQUIT,syscall.SIGTERM,syscall.SIGINT:
			closeChan <- struct{}{}
		}
	}()

	listener,err := net.Listen("tcp",cfg.Address)
	if err != nil {
		return err
	}

	ListenAndServe(listener,handler,closeChan)
	return nil
}

//ListenAndServer binds port and handle request 
func ListenAndServe(listener net.Listener, handler tcp.Handler, closeChan <-chan struct{}) {
	// listen signal
	go func() {
		<- closeChan
		fmt.Println("shutting down")
		_ = listener.Close()
		_ = handler.Close()
	}()

	// listen port
	defer func() {
		_ = listener.Close()
		_ = handler.Close()
	}()

	ctx := context.Background()
	var waitDone sync.WaitGroup
	for {
		conn, err := listener.Accept()
		if err != nil {
			break
		}
		fmt.Println("accept link")
		waitDone.Add(1)

		go func() {
			defer func() {
				waitDone.Done()
			}()
			handler.Handle(ctx, conn)
		}
	}
	waitDone.Wait()
}